package cn.qu.netty.boot;

import java.net.URLDecoder;

import com.alibaba.fastjson.JSONObject;

import cn.qu.util.TypeUtils;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

public class DefaultHandler extends SimpleChannelInboundHandler<HttpObject> {

	public DefaultHandler(FilterProvider filterProvider, HandlerMappingProvider handlerMappingProvider) {
		this.handlerMappingProvider = handlerMappingProvider;
		this.filterProvider = filterProvider;
	}

	private FilterProvider filterProvider;
	private HandlerMappingProvider handlerMappingProvider;

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
		FullHttpRequest req = (FullHttpRequest) msg;
		if (!filterProvider.getPer().isEmpty()) {
			filterProvider.getPer().forEach(f -> f.doFilter(req));
		}
		FullHttpResponse response = this.handler(req);
		if (!filterProvider.getAft().isEmpty()) {
			filterProvider.getAft().forEach(f -> f.doFilter(req, response));
		}
		ChannelFuture channelFuture = ctx.writeAndFlush(response);
		channelFuture.addListener(ChannelFutureListener.CLOSE);

	}

	private FullHttpResponse handler(FullHttpRequest req) {
		String method = req.method().name();
		FullHttpResponse response = null;
		try {
			String path = URLDecoder.decode(req.uri(), CharsetUtil.UTF_8.name());
			HandlerMapping handlerMapping = handlerMappingProvider.get(path, method);
			if (handlerMapping == null) {
				response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
				return response;
			}
			ParameterResolver parameterResolver = AbstractParameterResolver.get(handlerMapping.getHttpMethod());
			Object[] params;
			try {
				params = parameterResolver.resolve(req, handlerMapping);
				Object result = handlerMapping.getMethod().invoke(handlerMapping.getController(), params);
				String resultStr = "";
				if (result != null) {
					if (TypeUtils.isPojo(result.getClass())) {
						resultStr = JSONObject.toJSONString(result);
					} else { // 类型转换需要完善....
						resultStr = result.toString();
					}
				}
				ByteBuf content = Unpooled.copiedBuffer(resultStr, CharsetUtil.UTF_8);
				response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
				response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes())
						.set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON);
			} catch (ParameterResolverException e) {
				e.printStackTrace();
				response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
			}
		} catch (Exception e) {
			e.printStackTrace();
//			if (e instanceof IllegalArgumentException) {
			response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
//			}
		}

		return response;
	}

}
